﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using BGM.Domain.DTO;

namespace BGM.Application.View
{
    internal partial class XyCoordinateUserControl : UserControl
    {
        List<Reading> data;
        List<Ellipse> listOfMarkedEllipse;
        List<Line> listOfMarkedLines;

        List<Ellipse> listOfCurrentClickedEllipse;
        List<Line> listOfCurrentClickedLines;
        
        private double goodMin = 4;
        private double goodMax = 9;

        private double defaultPointSize = 7;        

        private double xoffset;
        private double yoffset;

        public XyCoordinateUserControl(Patient patient, List<Reading> data)
        {
            this.data = data;
            goodMin = patient.LevelIndicator.Low;
            goodMax = patient.LevelIndicator.High;

            InitializeComponent();
            xoffset = xCoordinateLine.X1;
            yoffset = yCoordinateLine.X1;
            drawPatientInfo(patient);
            drawPoints();            
            drawYScale();
            drawXScale();
            
        }

        private void drawPatientInfo(Patient patient)
        {
            int textOffset = 50;
            Label patientLabel = new Label();
            patientLabel.Content = patient.Name + " - " + patient.Ssn;
            Canvas.SetLeft(patientLabel, 0 + textOffset);
            canvas.Children.Add(patientLabel);

            Label high = new Label();
            high.Content = "High value: " + patient.LevelIndicator.High;
            Canvas.SetLeft(high, 0 + textOffset);
            Canvas.SetTop(high, 20);
            canvas.Children.Add(high);

            Label low = new Label();
            low.Content = "Low  value: " + patient.LevelIndicator.Low;
            Canvas.SetLeft(low, 0 + textOffset);
            Canvas.SetTop(low, 40);
            canvas.Children.Add(low);
        }
        private int convertTimeStampToSeconds(DateTime date)
        {
            return (date.Hour * 60 * 60) + (date.Minute * 60) + date.Second;
        }

        private void drawYScale()
        {
            for (int i = 1; i <= 30; i++)
            {
                TextBlock textBlock1 = new TextBlock();
                textBlock1.Height = 16;
                textBlock1.Text = i.ToString();

                Canvas.SetBottom(textBlock1, ((i*20)+100)-textBlock1.Height/2);
                Canvas.SetLeft(textBlock1,xoffset-20);
                canvas.Children.Add(textBlock1);


                Line line = new Line();
                line.StrokeThickness = 0.5;

                line.X1 = xCoordinateLine.X1;
                line.X2 = 900;
                line.Y1 = 0;
                line.Y2 = 0;

                DoubleCollection dashes = new DoubleCollection();
                dashes.Add(3);
                dashes.Add(6);
                line.StrokeDashArray = dashes;
                line.StrokeDashCap = PenLineCap.Round;
                
                Canvas.SetBottom(line, (i * 20) + 100);
                Canvas.SetLeft(line, 0);

                if (i == goodMin || i == goodMax)
                {
                    line.Stroke = Brushes.Red;
                    canvas.Children.Add(line);
                }
                else
                {
                    line.Stroke = Brushes.Green;                    
                }
                yCoordinateLine.Y2 = -i * 20 - 5;
            }

        }

        private void drawXScale()
        {
            DateTime date = new DateTime(2000, 12, 24, 23, 59, 00);

            for (int i = 0; i < 6; i++)
            {
                TextBlock textBlock1 = new TextBlock();
                textBlock1.Text = date.ToString("HH:mm");
                textBlock1.Width = 30;
                textBlock1.HorizontalAlignment = HorizontalAlignment.Center;


                Canvas.SetBottom(textBlock1, 80);
                Canvas.SetLeft(textBlock1, xoffset + (convertTimeStampToSeconds(date) / 100) - textBlock1.Width / 2);
                canvas.Children.Add(textBlock1);


                Line line = new Line();
                line.StrokeThickness = 0.5;
                line.Stroke = Brushes.Red;
                line.X1 = 0;
                line.X2 = 0;
                line.Y1 = 0;
                line.Y2 = yCoordinateLine.Y2;

                DoubleCollection dashes = new DoubleCollection();
                dashes.Add(3);
                dashes.Add(6);
                line.StrokeDashArray = dashes;
                line.StrokeDashCap = PenLineCap.Round;

                Canvas.SetBottom(line, 100);
                Canvas.SetLeft(line, xoffset + convertTimeStampToSeconds(date) / 100);
                canvas.Children.Add(line);

                if (i == 0)
                {
                    xCoordinateLine.X2 = xoffset + convertTimeStampToSeconds(date) / 100;
                    date = date.AddMinutes(1.00);
                    
                    
                }
                date = date.AddHours(4);

                
            }
            
        }

        private void drawPoints()
        {
            foreach (Reading reading in data)
            {
                Ellipse ellipse = new Ellipse();
                ellipse.Height = defaultPointSize;
                ellipse.Width = ellipse.Height;

                ellipse.Tag = reading;
                givePointColor(ellipse);
                Canvas.SetBottom(ellipse, (((reading.Value/18.00)*20)+100)-(ellipse.Height/2));
                Canvas.SetLeft(ellipse, xoffset + (convertTimeStampToSeconds(reading.TimeStamp) / 100) - ellipse.Width / 2);

                ellipse.MouseEnter += new MouseEventHandler(ellipse_MouseEnter);
                ellipse.MouseLeave += new MouseEventHandler(ellipse_MouseLeave);
                ellipse.MouseLeftButtonDown += new MouseButtonEventHandler(ellipse_MouseLeftButtonDown);
                
                //Console.WriteLine("Seconds " + convertTimeStampToSeconds(reading.TimeStamp) / 100);
                canvas.Children.Add(ellipse);
            }
        }

        private void givePointColor(Ellipse ellipse)
        {   
            Reading reading = ellipse.Tag as Reading;
            if (reading.Value/18.00 >= goodMin && reading.Value/18.00 <= goodMax)
            {
                ellipse.Fill = Brushes.Blue;
            }
            else
                ellipse.Fill = Brushes.Red;
        }

        private void drawLines(List<Ellipse> Ellipselist, List<Line> lineList)
        {

            for (int i = Ellipselist.Count - 1; i >= 0; i--) //
            {
                Ellipse ellipse = Ellipselist[i];

                if (i - 1 < 0)
                {
                    break;
                }
                Ellipse next = Ellipselist[i - 1];

                if (ellipse != null && next != null)
                {
                    Line line = new Line();
                    line.Stroke = Brushes.Black;
                    line.StrokeThickness = 1;

                    double yCor = (Canvas.GetBottom(ellipse) - Canvas.GetBottom(next));
                    double xCor = (Canvas.GetLeft(ellipse) - Canvas.GetLeft(next));

                    if (yCor > 0)
                    {
                        line.Y2 = Math.Abs(yCor);
                        line.X1 = Math.Abs(xCor);
                        Canvas.SetLeft(line, Canvas.GetLeft(next) + defaultPointSize / 2);
                        Canvas.SetBottom(line, (Canvas.GetBottom(next) + defaultPointSize / 2) - line.StrokeThickness / 2);
                    }
                    else
                    {
                        xCor = Canvas.GetLeft(next) - Canvas.GetLeft(ellipse);

                        line.Y1 = Math.Abs(yCor);
                        line.X2 = xCor;
                        Canvas.SetLeft(line, Canvas.GetLeft(ellipse) + defaultPointSize / 2);
                        Canvas.SetBottom(line, (Canvas.GetBottom(ellipse) + defaultPointSize / 2) - line.StrokeThickness / 2);
                    }

                    lineList.Add(line);
                }

            }
            foreach (Line line in lineList)
            {
                if (!canvas.Children.Contains(line))
                {
                    canvas.Children.Add(line);
                }
            }

            InvalidateVisual();
        }

        private void removeLines(List<Line> list)
        {
            foreach (Line line in list)
            {
                canvas.Children.Remove(line);
            }
            InvalidateVisual();
        }

        void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            
            if (listOfCurrentClickedLines != null)
            {
                removeLines(listOfCurrentClickedLines);
            }

            listOfCurrentClickedEllipse = new List<Ellipse>();
            listOfCurrentClickedLines = new List<Line>();

            foreach (Ellipse ellipse in listOfMarkedEllipse)
            {
                listOfCurrentClickedEllipse.Add(ellipse);
            }

            foreach (Line line in listOfMarkedLines)
            {
                listOfCurrentClickedLines.Add(line);
            }
            InvalidateVisual();

            drawLines(listOfCurrentClickedEllipse, listOfCurrentClickedLines);

            
        }

        void ellipse_MouseLeave(object sender, MouseEventArgs e)
        {   
            foreach (Object ellipse in canvas.Children)
            {
                foreach (Ellipse working in listOfMarkedEllipse)
                {

                    if (ellipse is Ellipse)
                    {
                        if (working.Equals(ellipse))
                        {
                            givePointColor((Ellipse)ellipse);
                        }

                    }
                }
	        }
            canvas.Children.Remove(selectedPointDescription);
            
            removeLines(listOfMarkedLines);            
        }
        Label selectedPointDescription;
        void ellipse_MouseEnter(object sender, MouseEventArgs e)
        {            
            this.listOfMarkedEllipse = new List<Ellipse>();
            this.listOfMarkedLines = new List<Line>();

            Reading found = ((Ellipse)sender).Tag as Reading;
            Point p= new Point();
            bool found1 = false;
            foreach (Object ellipse in canvas.Children)
            {
                if (ellipse is Ellipse)
                {
                    if(!found1)
                    {
                    p= (e.GetPosition(this));
                        found1=true;

                        selectedPointDescription = new Label();
                        Reading reading = ((ellipse as Ellipse).Tag as Reading);
                        System.Globalization.CultureInfo cu = new System.Globalization.CultureInfo("en-US",false);
                        cu.NumberFormat.NumberDecimalDigits = 2;
                        selectedPointDescription.Content = reading.TimeStamp.ToString() + " - "+(reading.Value/18).ToString(cu.NumberFormat);
                    }
                    Reading investigate = ((Ellipse)ellipse).Tag as Reading;

                    if (found.TimeStamp.Year.Equals(investigate.TimeStamp.Year) && found.TimeStamp.Month.Equals(investigate.TimeStamp.Month) && found.TimeStamp.Day.Equals(investigate.TimeStamp.Day))
                    {
                        ((Ellipse)ellipse).Fill = Brushes.Green;


                        listOfMarkedEllipse.Add((Ellipse)ellipse);
                    }
                }
            }



           
            Canvas.SetLeft(selectedPointDescription, p.X);
            Canvas.SetTop(selectedPointDescription, p.Y-25);
            canvas.Children.Add(selectedPointDescription);


            drawLines(listOfMarkedEllipse, listOfMarkedLines);
            
        }
    }
}
